<?php

namespace app\web\service;

use app\common\logic\CarLogic;
use app\common\logic\OrderLogic;
use app\common\logic\PayLogic;
use app\common\model\commonModel;
use app\common\model\trCache;
use app\common\model\trCarLine;
use app\common\model\trCarType;
use app\common\model\trOrder;
use app\common\model\trResource;
use app\common\model\trSystemSet;
use app\common\model\trUser;
use app\common\util\ErrorCode;
use app\common\util\Tools;
use app\common\util\WxPay;

/**
 * Class Auth
 * @package app\web\service
 * 专车接送服务类
 */
class CarService
{
    private $params;
    private $returnData;
    private $mallId = 0;

    public function __construct($data, $params)
    {
        $this->returnData = $data;
        $this->params = $params;
        $this->mallId = request()->mallData["id"];
    }

    // 获取下订单页的数据
    public function getOrderData(){
        $this->returnData["data"] = ["remark" => CarLogic::getLineRemark()];
        return $this->returnData;
    }

    // 线路数据，匹配精确到省市区
    public function getLineData(){
        $model = new trCarLine();
        // 获取出发地和目的地筛选的数据
        $goData = $destinationDate = [];
        if(($redisObject = redis_object()) !== false) {// 是redis缓存
            $fromData = $redisObject->zRange("{$this->mallId}_".$model->fromCacheText,0,-1, true); // 拿出发地code(score)和线路ID(member)
            if(empty($fromData)){
                $model->toSaveFromCache(); //检查缓存
                $fromData = $redisObject->zRange("{$this->mallId}_".$model->fromCacheText,0,-1, true); // 拿出发地code(score)和线路ID(member)
            }
            if(!empty($fromData)){ // 有数据
                foreach ($fromData as $id => $provinceCodeFrom){ // 出发地
                    if(empty($lineData[$id])){
                        $lineData[$id] = $model->getPCACacheData($id);
                    }
                    if($provinceCodeFrom == $lineData[$id]["provinceCodeFrom"] && empty($goData["temp"][$provinceCodeFrom.$lineData[$id]["cityCodeFrom"].$lineData[$id]["areaCodeFrom"]])){
                        $goData[] = [
                            $provinceCodeFrom, $lineData[$id]["cityCodeFrom"], $lineData[$id]["areaCodeFrom"],
                            Tools::getNameByPCA($provinceCodeFrom, $lineData[$id]["cityCodeFrom"], $lineData[$id]["areaCodeFrom"])
                        ];
                        $goData["temp"][$provinceCodeFrom.$lineData[$id]["cityCodeFrom"].$lineData[$id]["areaCodeFrom"]] = true;
                    }
                    if(empty($destinationDate["temp"][$provinceCodeFrom])) { //  所有目的地，减少查询次数
                        $destinationDate["temp"][$provinceCodeFrom] = $redisObject->zRange("{$this->mallId}_".$model->toCacheText . $provinceCodeFrom, 0, -1, true); // 拿目的地code(score)和线路ID(member)
                        foreach ($destinationDate["temp"][$provinceCodeFrom] as $dId => $provinceCodeTo) { // 目的地
                            if(empty($lineData[$dId])){ // 因为是在foreach里，$lineData[$dId]可能是空的，外层的$id和$dId可能不一致
                                $lineData[$dId] = $model->getPCACacheData($dId);
                            }
                            $destinationDate[$provinceCodeFrom][$lineData[$dId]["cityCodeFrom"]][$lineData[$dId]["areaCodeFrom"]][] = [
                                "name" => Tools::getNameByPCA($provinceCodeTo, $lineData[$dId]["cityCodeTo"], $lineData[$dId]["areaCodeTo"]),
                                "lineId" => $dId,
                                "carType" => $lineData[$dId]["carType"]
                            ];
                        }
                    }
                }
                unset($goData["temp"]);
                unset($destinationDate["temp"]);
            }
        }else{
            $database = $model->getFields("id,province_code_from,city_code_from,area_code_from,province_code_to,city_code_to,area_code_to,car_type", ["status" => 1, "mall_id" => $this->mallId], false, false);
            if(!empty($database)) {
                foreach ($database as $item) {
                    $item = Tools::transferFields($item->getData());
                    if (empty($goData["temp"][$item["provinceCodeFrom"] . $item["cityCodeFrom"] . $item["areaCodeFrom"]])) {
                        $goData[] = [
                            $item["provinceCodeFrom"], $item["cityCodeFrom"], $item["areaCodeFrom"],
                            Tools::getNameByPCA($item["provinceCodeFrom"], $item["cityCodeFrom"], $item["areaCodeFrom"])
                        ];
                        $goData["temp"][$item["provinceCodeFrom"] . $item["cityCodeFrom"] . $item["areaCodeFrom"]] = true;
                    }
                    $destinationDate[$item["provinceCodeFrom"]][$item["cityCodeFrom"]][$item["areaCodeFrom"]][] = [
                        "name" => Tools::getNameByPCA($item["provinceCodeTo"], $item["cityCodeTo"], $item["areaCodeTo"]),
                        "lineId" => $item["id"],
                        "carType" => $item["carType"]
                    ];
                }
                unset($goData["temp"]);
            }
        }
        return [$goData, $destinationDate];
    }

    public function getOrderSure($userId){
        if (!empty($this->params['addressFromLatitude']) && !empty($this->params["addressFromLongitude"])) {
            $res = CarLogic::getDetailAddress($this->params["addressFromLatitude"], $this->params["addressFromLongitude"]);
            if(isset($res["code"])){
                return $res;
            }
            $this->params['addressFrom'] = $res;
        }elseif (empty($this->params['addressFrom'])) {
            return ErrorCode::code("customized", "记得选择上下车地点哦~");
        }
        if (!empty($this->params['addressToLatitude']) && !empty($this->params["addressToLongitude"])) {
            $res = CarLogic::getDetailAddress($this->params["addressToLatitude"], $this->params["addressToLongitude"]);
            if(isset($res["code"])){
                return $res;
            }
            $this->params['addressTo'] = $res;
        }elseif (empty($this->params['addressTo'])) {
            return ErrorCode::code("customized", "记得选择上下车地点哦~");
        }
        if (empty($this->params['chooseTime'])) {
            return ErrorCode::code("params_not_exist", "选择日期");
        }
        list($goData, $destinationDate) = $this->getLineData(); // 获取所有专车接送的出发地和目的地数据
        $provinceFromCode = $cityCodeFrom = $areaCodeFrom = $addressFrom = 0;
        foreach ($goData as $item){
            $pcaAddress = str_replace(" ", "", $item[3]);
            if(strpos($this->params["addressFrom"], $pcaAddress) !== false){ // 根据省市区格式匹配出发地
                $provinceFromCode = $item[0];
                $cityCodeFrom = $item[1];
                $areaCodeFrom = $item[2];
                $addressFrom = $item[3] . " " . substr($this->params["addressFrom"], strlen($pcaAddress));
                break; // 结束这个foreach
            }
        }
        if(empty($provinceFromCode)){
            return ErrorCode::code("customized", "区域未开通");
        }
        $model = new trCarLine();
        $carTypeModel = new trCarType();
        $no = 0;
        foreach ($destinationDate[$provinceFromCode][$cityCodeFrom][$areaCodeFrom] as $item){
            $pcaAddress = str_replace(" ", "", $item["name"]);
            if(strpos($this->params["addressTo"], $pcaAddress) !== false){ // 匹配上了目的地
                if($redisObject = redis_object() !== false) {
                    $data = $model->getFields("id,open_default,open_weekend,open_date,date_between,default_price,weekend_price,date_price,charge_type", ["id" => $item["lineId"]], true, false);
                    $data = array_merge($data, $model->getPCACacheData($item["lineId"]));
                }else{
                    $data = $model->getFields(
                        "id,open_default,open_weekend,open_date,date_between,default_price,weekend_price,date_price,charge_type,province_code_from,city_code_from,area_code_from,province_code_to,city_code_to,area_code_to,car_type",
                        ["id" => $item["lineId"]], true, false
                    );
                }
                if(empty($data)){
                    continue;
                }
                if($type = CarLogic::getJudgeOpenType($data, $this->params["chooseTime"])) { //  1：日期；2：周末；3：默认
                    if(empty($typeName[$item["carType"]])) { // 减少数据库查询次数，可能这个车型已经查过了
                        $typeName[$item["carType"]] = $carTypeModel->getFields("name,seat,icon,remark", ["id" => $item["carType"]]);
                    }
                    $cacheKey = Tools::createGUID();
                    $data["addressTo"] = $item["name"] . " " . substr($this->params["addressTo"], strlen($pcaAddress));
                    $data["addressFrom"] = $addressFrom;
                    $data["longLatFrom"] = (isset($this->params["addressFromLongitude"]) ? $this->params["addressFromLongitude"] : 0) . "," . (isset($this->params["addressFromLatitude"]) ? $this->params["addressFromLatitude"] : 0);
                    $data["longLatTo"] = (isset($this->params["addressToLongitude"]) ? $this->params["addressToLongitude"] : 0) . "," . (isset($this->params["addressToLatitude"]) ? $this->params["addressToLatitude"] : 0);
                    $data["rideNumber"] = $typeName[$item["carType"]]["seat"];
                    trCache::saveCache(["key" => $cacheKey . $userId, "value" => $data, "time" => 600]);
                    $chooseData[] = [
                        "lineId" => $item["lineId"], "rideNumber" => $data["rideNumber"], "money" => CarLogic::getShowPrice($data, $type), "orderKey" => $cacheKey,
                        "carTypeName" => $typeName[$item["carType"]]["name"], "carTypeRemark" => $typeName[$item["carType"]]["remark"],
                        "carTypeIcon" => tome_dia(trResource::getValue("url", ["id" => $typeName[$item["carType"]]["icon"]])),
                        "chargeType" => $data["chargeType"]
                    ];
                }else{
                    $no = 1;
                }
            }else{
                $no = 2;
            }
        }
        if(empty($chooseData)){
            return ErrorCode::code("customized", $no == "2" ? "区域未开通" : "区域未在此时间内开通");
        }
        $this->returnData["data"] = $chooseData;
        return $this->returnData;
    }

    // 提交订单
    public function toSubmitOrder($userId, $openid){
        $field = [
            "orderKey" => "orderKey", "chooseTime" => "选择日期", "shiftTime" => "选择时间", "contactId" => "联系人", "rideNumber" => "乘车人数"
        ];
        foreach ($field as $k => $v) {
            if(!isset($this->params[$k])){
                $this->returnData = ErrorCode::code('params_not_exist', $v);
                return $this->returnData;
            }
        }
        $cacheData = trCache::getValue("value", ["key" => $this->params["orderKey"] . $userId]);
        if(empty($cacheData)){
            $this->returnData = ErrorCode::code("fail");
            $this->returnData["msg"] = "订单已创建";
            return $this->returnData;
        }
        if(!is_numeric($this->params["rideNumber"])){
            return ErrorCode::code("params_format", "乘车人数");
        }
        if($cacheData["rideNumber"] < $this->params["rideNumber"]){
            $this->returnData = ErrorCode::code("fail");
            $this->returnData["msg"] = "乘车人数超过座位量";
            return $this->returnData;
        }
        $this->params["rideNumber"] = intval($this->params["rideNumber"]);
        if(!($type = CarLogic::getJudgeOpenType($cacheData, $this->params['chooseTime']))){
            return ErrorCode::code("customized", "该{$this->params['chooseTime']}时间没有开通");
        }
        $contactData = commonModel::getFields(contactTable, "prefix,mobile,name", ["id" => $this->params["contactId"], "user_id" => $userId], true, false);
        if(empty($contactData)){
            return ErrorCode::code("params_error", "contactId（联系人ID）");
        }
        // 计算总价、计算佣金
        $model = new trCarLine();
        $data = $model->getFields("default_commission,weekend_commission,date_commission", ["id" => $cacheData["id"]], true, false);
        if($cacheData["chargeType"] == "0"){ // 按人头
            $totalMoney = CarLogic::getShowPrice($cacheData, $type) * $this->params["rideNumber"];
        }else{ // 按车辆
            $totalMoney = CarLogic::getShowPrice($cacheData, $type);
        }
        $commission = CarLogic::getShowCommission($data, $type);
        if(empty($totalMoney)){
            return ErrorCode::code("customized", "价格有误");
        }
        // 使用优惠券
        $couponAmount = 0; // 优惠金额
        $userCouponId = 0;
        if(!empty($this->params['userCouponId']) && !empty($couponInfo = commonModel::getFields(userCouponTable,'amount',['id' => $this->params['userCouponId']]))){
            $userCouponId = $this->params['userCouponId'];
            $couponAmount = $couponInfo['amount'];
        }elseif(!empty($this->params["coupon"]) && !empty($couponInfo = commonModel::getFields(userCouponTable,'id,amount',["coupon_id" => $this->params["coupon"], "user_id" => $userId]))){
            $userCouponId = $couponInfo["id"];
            $couponAmount = $couponInfo['amount'];
        }
        $orderModel = new trOrder();
        $orderSn = $orderModel->getSn();
        $paymentNo = $orderModel->getPayNo();
        $orderData = [
            "order_sn" => $orderSn,
            "mall_id" => $this->mallId,
            "line_id" => $cacheData["id"],
            "user_id" => $userId,
            "contact_name" => $contactData["name"],
            "mobile" => $contactData["prefix"].$contactData["mobile"],
            "ride_number" => $this->params["rideNumber"],   // 总票数
            "total_money" => $totalMoney,  // 订单总价格
            "pay_money" => $totalMoney > $couponAmount ? $totalMoney - $couponAmount : 0,  // 去支付的价格
            "discount_money" => $couponAmount, // 没接优惠券，所有默认0
            "commission" => $commission,
            "coupon_id" => $userCouponId,     //新 用户优惠券表 id
            "reserve_time" => $this->params["chooseTime"] . " " . $this->params["shiftTime"], // 预约时间，出发时间
            "type" => 3,   //类型；1机场接送，2巴士路线，3专车接送
            "payment_no" => $paymentNo,
            "memo" => isset($this->params["memo"]) ? $this->params["memo"] : "",
            "long_lat_from" => $cacheData["longLatFrom"],
            "long_lat_to" => $cacheData["longLatTo"],
        ];
        if (!empty($cacheData["addressTo"]) && !empty($cacheData["addressFrom"])) {
            $orderData["address_from"] = $cacheData["addressFrom"];
            $orderData["address_to"] = $cacheData["addressTo"];
        }else{
            $orderData["address_from"] = Tools::getNameByPCA($cacheData["provinceCodeFrom"], $cacheData["cityCodeFrom"], $cacheData["areaCodeFrom"]);
            $orderData["address_to"] = Tools::getNameByPCA($cacheData["provinceCodeTo"], $cacheData["cityCodeTo"], $cacheData["areaCodeTo"]);
        }
        if($orderId = $orderModel->add($orderData, true)){
            if(!empty($this->params["formId"]) && strpos($this->params["formId"], "the formId") === false){ // 存 form_id
                commonModel::toAdd(formIdTable, ["user_id" => $userId, "form_id" => $this->params["formId"], "type" => "prepay_id", "create_time" => time(), "mall_id" => $this->mallId]);
            }
            trCache::del($this->params["orderKey"] . $userId);
            //订单后续操作
            if($orderData["pay_money"]) {
                $data = [
                    "total_fee" => $orderData["pay_money"] * 100, "openid" => $openid, "out_trade_no" => $paymentNo, "body" => "专车接送支付"
                ];
                // 加的测试
                if (in_array(request()->host(), ["cardemo.wegouer.com/test/cars-pai", "service-emhatyrq-1251017581.gz.apigw.tencentcs.com/test/cars-pai"])) {
//                $data["total_fee"] = 1; // 测试 1毛
                }
                $wxPay = new WxPay();
                $res = $wxPay->toPay($data); // 获取支付信息
                if (isset($res["code"])) {
                    $this->returnData = $res;
                } else {
                    // 订单有效时间为30分钟，时间一到就要自动取消
                    OrderLogic::cancelOrderJobs($orderSn, ["orderSn" => $orderSn, "userId" => $userId]);
                    $res["orderSn"] = $orderSn;
                    $this->returnData["data"] = $res;
                }
            }else{
                $payLogic = new PayLogic();
                $userModel = new trUser();
                $payLogic->updateOrder($paymentNo, ["tradeNo" => "", "totalFee" => 0, "payAccount" => $userModel->getValue("nickname", ["id" => $userId])]);
                $this->returnData["data"] = ["orderSn" => $orderSn];
            }
        }else{
            $this->returnData = ErrorCode::code("fail");
            $this->returnData["msg"] = "生成订单失败";
        }
        return $this->returnData;
    }
}